From c3b43f2ad216479c900c0b7cfd56e8de680f54c0 Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Thu, 11 Jun 2020 19:59:35 -0400 Subject: [PATCH] printeroptionwidget: Port to GtkDropDown Use GtkDropDown instead of GtkComboBox in the print dialog. --- gtk/gtkprinteroptionwidget.c | 433 +++++++++++++++++++++++++---------- 1 file changed, 311 insertions(+), 122 deletions(-) diff --git a/gtk/gtkprinteroptionwidget.c b/gtk/gtkprinteroptionwidget.c index a63d614806..b83040f404 100644 --- a/gtk/gtkprinteroptionwidget.c +++ b/gtk/gtkprinteroptionwidget.c @@ -23,9 +23,10 @@ #include "gtkintl.h" #include "gtkcheckbutton.h" -#include "gtkcelllayout.h" -#include "gtkcellrenderertext.h" -#include "gtkcombobox.h" +#include "gtkdropdown.h" +#include "gtklistitem.h" +#include "gtksignallistitemfactory.h" +#include "gtkentry.h" #include "gtkfilechooserdialog.h" #include "gtkimage.h" #include "gtklabel.h" @@ -263,168 +264,357 @@ gtk_printer_option_widget_set_source (GtkPrinterOptionWidget *widget, g_object_notify (G_OBJECT (widget), "source"); } +#define GTK_TYPE_STRING_PAIR (gtk_string_pair_get_type ()) +G_DECLARE_FINAL_TYPE (GtkStringPair, gtk_string_pair, GTK, STRING_PAIR, GObject) + +struct _GtkStringPair { + GObject parent_instance; + char *id; + char *string; +}; + enum { - NAME_COLUMN, - VALUE_COLUMN, - N_COLUMNS + PROP_ID = 1, + PROP_STRING, + PROP_NUM_PROPERTIES }; +G_DEFINE_TYPE (GtkStringPair, gtk_string_pair, G_TYPE_OBJECT); + +static void +gtk_string_pair_init (GtkStringPair *pair) +{ +} + +static void +gtk_string_pair_finalize (GObject *object) +{ + GtkStringPair *pair = GTK_STRING_PAIR (object); + + g_free (pair->id); + g_free (pair->string); + + G_OBJECT_CLASS (gtk_string_pair_parent_class)->finalize (object); +} + +static void +gtk_string_pair_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + GtkStringPair *pair = GTK_STRING_PAIR (object); + + switch (property_id) + { + case PROP_STRING: + g_free (pair->string); + pair->string = g_value_dup_string (value); + break; + + case PROP_ID: + g_free (pair->id); + pair->id = g_value_dup_string (value); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static void +gtk_string_pair_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + GtkStringPair *pair = GTK_STRING_PAIR (object); + + switch (property_id) + { + case PROP_STRING: + g_value_set_string (value, pair->string); + break; + + case PROP_ID: + g_value_set_string (value, pair->id); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static void +gtk_string_pair_class_init (GtkStringPairClass *class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (class); + GParamSpec *pspec; + + object_class->finalize = gtk_string_pair_finalize; + object_class->set_property = gtk_string_pair_set_property; + object_class->get_property = gtk_string_pair_get_property; + + pspec = g_param_spec_string ("string", "String", "String", + NULL, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + g_object_class_install_property (object_class, PROP_STRING, pspec); + + pspec = g_param_spec_string ("id", "ID", "ID", + NULL, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS); + + g_object_class_install_property (object_class, PROP_ID, pspec); +} + +static GtkStringPair * +gtk_string_pair_new (const char *id, + const char *string) +{ + return g_object_new (GTK_TYPE_STRING_PAIR, + "id", id, + "string", string, + NULL); +} + +static const char * +gtk_string_pair_get_string (GtkStringPair *pair) +{ + return pair->string; +} + +static const char * +gtk_string_pair_get_id (GtkStringPair *pair) +{ + return pair->id; +} + static void combo_box_set_model (GtkWidget *combo_box) { - GtkListStore *store; + GListStore *store; - store = gtk_list_store_new (N_COLUMNS, G_TYPE_STRING, G_TYPE_STRING); - gtk_combo_box_set_model (GTK_COMBO_BOX (combo_box), GTK_TREE_MODEL (store)); + store = g_list_store_new (GTK_TYPE_STRING_PAIR); + gtk_drop_down_set_model (GTK_DROP_DOWN (combo_box), G_LIST_MODEL (store)); g_object_unref (store); } +static void +setup_no_item (GtkSignalListItemFactory *factory, + GtkListItem *item) +{ +} + +static void +setup_list_item (GtkSignalListItemFactory *factory, + GtkListItem *item) +{ + GtkWidget *label; + + label = gtk_label_new (""); + gtk_widget_set_halign (label, GTK_ALIGN_START); + gtk_list_item_set_child (item, label); +} + +static void +bind_list_item (GtkSignalListItemFactory *factory, + GtkListItem *item) +{ + GtkStringPair *pair; + GtkWidget *label; + + pair = gtk_list_item_get_item (item); + label = gtk_list_item_get_child (item); + + gtk_label_set_text (GTK_LABEL (label), gtk_string_pair_get_string (pair)); +} + static void combo_box_set_view (GtkWidget *combo_box) { - GtkCellRenderer *cell; + GtkListItemFactory *factory; + + factory = gtk_signal_list_item_factory_new (); + g_signal_connect (factory, "setup", G_CALLBACK (setup_list_item), NULL); + g_signal_connect (factory, "bind", G_CALLBACK (bind_list_item), NULL); + gtk_drop_down_set_factory (GTK_DROP_DOWN (combo_box), factory); + g_object_unref (factory); +} + +static void +selected_changed (GtkDropDown *dropdown, + GParamSpec *pspec, + gpointer data) +{ + GListModel *model; + guint selected; + GtkStringPair *pair; + GtkWidget *entry = data; + + model = gtk_drop_down_get_model (dropdown); + selected = gtk_drop_down_get_selected (dropdown); + + pair = g_list_model_get_item (model, selected); + if (pair) + { + gtk_editable_set_text (GTK_EDITABLE (entry), gtk_string_pair_get_string (pair)); + g_object_unref (pair); + } + else + gtk_editable_set_text (GTK_EDITABLE (entry), ""); - cell = gtk_cell_renderer_text_new (); - gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combo_box), cell, TRUE); - gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (combo_box), cell, - "text", NAME_COLUMN, - NULL); } static GtkWidget * combo_box_entry_new (void) { - GtkWidget *combo_box; - combo_box = g_object_new (GTK_TYPE_COMBO_BOX, "has-entry", TRUE, NULL); + GtkWidget *hbox, *entry, *button; + GtkListItemFactory *factory; - combo_box_set_model (combo_box); + hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0); + gtk_widget_add_css_class (hbox, "linked"); - gtk_combo_box_set_entry_text_column (GTK_COMBO_BOX (combo_box), NAME_COLUMN); + entry = gtk_entry_new (); + button = gtk_drop_down_new (); + combo_box_set_model (button); - return combo_box; + factory = gtk_signal_list_item_factory_new (); + g_signal_connect (factory, "setup", G_CALLBACK (setup_no_item), NULL); + gtk_drop_down_set_factory (GTK_DROP_DOWN (button), factory); + g_object_unref (factory); + + factory = gtk_signal_list_item_factory_new (); + g_signal_connect (factory, "setup", G_CALLBACK (setup_list_item), NULL); + g_signal_connect (factory, "bind", G_CALLBACK (bind_list_item), NULL); + gtk_drop_down_set_list_factory (GTK_DROP_DOWN (button), factory); + g_object_unref (factory); + + g_signal_connect (button, "notify::selected", G_CALLBACK (selected_changed), entry); + + gtk_box_append (GTK_BOX (hbox), entry); + gtk_box_append (GTK_BOX (hbox), button); + + return hbox; } static GtkWidget * combo_box_new (void) { GtkWidget *combo_box; - combo_box = gtk_combo_box_new (); + + combo_box = gtk_drop_down_new (); combo_box_set_model (combo_box); combo_box_set_view (combo_box); return combo_box; } - + static void combo_box_append (GtkWidget *combo, - const gchar *display_text, - const gchar *value) + const gchar *display_text, + const gchar *value) { - GtkTreeModel *model; - GtkListStore *store; - GtkTreeIter iter; - - model = gtk_combo_box_get_model (GTK_COMBO_BOX (combo)); - store = GTK_LIST_STORE (model); - - gtk_list_store_append (store, &iter); - gtk_list_store_set (store, &iter, - NAME_COLUMN, display_text, - VALUE_COLUMN, value, - -1); -} + GtkWidget *dropdown; + GListModel *model; + GtkStringPair *object; -struct ComboSet { - GtkComboBox *combo; - const gchar *value; -}; + if (GTK_IS_DROP_DOWN (combo)) + dropdown = combo; + else + dropdown = gtk_widget_get_last_child (combo); -static gboolean -set_cb (GtkTreeModel *model, - GtkTreePath *path, - GtkTreeIter *iter, - gpointer data) -{ - struct ComboSet *set_data = data; - gboolean found; - char *value; - - gtk_tree_model_get (model, iter, VALUE_COLUMN, &value, -1); - found = (strcmp (value, set_data->value) == 0); - g_free (value); - - if (found) - gtk_combo_box_set_active_iter (set_data->combo, iter); + model = gtk_drop_down_get_model (GTK_DROP_DOWN (dropdown)); - return found; + object = gtk_string_pair_new (value, display_text); + g_list_store_append (G_LIST_STORE (model), object); + g_object_unref (object); } static void combo_box_set (GtkWidget *combo, - const gchar *value) + const gchar *value) { - GtkTreeModel *model; - struct ComboSet set_data; - - model = gtk_combo_box_get_model (GTK_COMBO_BOX (combo)); + GtkWidget *dropdown; + GListModel *model; + guint i; + + if (GTK_IS_DROP_DOWN (combo)) + dropdown = combo; + else + dropdown = gtk_widget_get_last_child (combo); - set_data.combo = GTK_COMBO_BOX (combo); - set_data.value = value; - gtk_tree_model_foreach (model, set_cb, &set_data); + model = gtk_drop_down_get_model (GTK_DROP_DOWN (dropdown)); + + for (i = 0; i < g_list_model_get_n_items (model); i++) + { + GtkStringPair *item = g_list_model_get_item (model, i); + if (strcmp (value, gtk_string_pair_get_id (item)) == 0) + { + gtk_drop_down_set_selected (GTK_DROP_DOWN (dropdown), i); + g_object_unref (item); + break; + } + g_object_unref (item); + } } static gchar * combo_box_get (GtkWidget *combo, gboolean *custom) { - GtkTreeModel *model; - gchar *value; - GtkTreeIter iter; + GtkWidget *dropdown; + GListModel *model; + guint selected; + gpointer item; + const char *id; + const char *string; + + if (GTK_IS_DROP_DOWN (combo)) + dropdown = combo; + else + dropdown = gtk_widget_get_last_child (combo); - model = gtk_combo_box_get_model (GTK_COMBO_BOX (combo)); + model = gtk_drop_down_get_model (GTK_DROP_DOWN (dropdown)); + selected = gtk_drop_down_get_selected (GTK_DROP_DOWN (dropdown)); + item = g_list_model_get_item (model, selected); + if (item) + { + id = gtk_string_pair_get_id (item); + string = gtk_string_pair_get_string (item); + g_object_unref (item); + } + else + { + id = ""; + string = NULL; + } - value = NULL; - if (gtk_combo_box_get_active_iter (GTK_COMBO_BOX (combo), &iter)) + if (dropdown == combo) // no entry { - gtk_tree_model_get (model, &iter, VALUE_COLUMN, &value, -1); *custom = FALSE; + return g_strdup (id); } else { - if (gtk_combo_box_get_has_entry (GTK_COMBO_BOX (combo))) + const char *text; + + text = gtk_editable_get_text (GTK_EDITABLE (gtk_widget_get_first_child (combo))); + if (g_strcmp0 (text, string) == 0) { - value = g_strdup (gtk_editable_get_text (GTK_EDITABLE (gtk_combo_box_get_child (GTK_COMBO_BOX (combo))))); - *custom = TRUE; + *custom = FALSE; + return g_strdup (id); } - - if (!value || !gtk_tree_model_get_iter_first (model, &iter)) - return value; - - /* If the user entered an item from the dropdown list manually, return - * the non-custom option instead. */ - do + else { - gchar *val, *name; - gtk_tree_model_get (model, &iter, VALUE_COLUMN, &val, - NAME_COLUMN, &name, -1); - if (g_str_equal (value, name)) - { - *custom = FALSE; - g_free (name); - g_free (value); - return val; - } - - g_free (val); - g_free (name); + *custom = TRUE; + return g_strdup (text); } - while (gtk_tree_model_iter_next (model, &iter)); } - - return value; } - static void deconstruct_widgets (GtkPrinterOptionWidget *widget) { @@ -594,6 +784,7 @@ filter_numeric (const gchar *val, static void combo_changed_cb (GtkWidget *combo, + GParamSpec *pspec, GtkPrinterOptionWidget *widget) { GtkPrinterOptionWidgetPrivate *priv = widget->priv; @@ -604,7 +795,7 @@ combo_changed_cb (GtkWidget *combo, g_signal_handler_block (priv->source, priv->source_changed_handler); - value = combo_box_get (combo, &custom); + value = combo_box_get (priv->combo, &custom); /* Handle constraints if the user entered a custom value. */ if (custom) @@ -639,12 +830,9 @@ combo_changed_cb (GtkWidget *combo, if (changed) { - GtkEntry *entry; - - entry = GTK_ENTRY (gtk_combo_box_get_child (GTK_COMBO_BOX (combo))); - + GtkWidget *entry = gtk_widget_get_first_child (priv->combo); gtk_editable_set_text (GTK_EDITABLE (entry), filtered_val); - } + } value = filtered_val; } @@ -746,9 +934,12 @@ construct_widgets (GtkPrinterOptionWidget *widget) if (source == NULL) { - priv->combo = combo_box_new (); - combo_box_append (priv->combo,_("Not available"), "None"); - gtk_combo_box_set_active (GTK_COMBO_BOX (priv->combo), 0); + const char * strings[2]; + strings[0] = _("Not available"); + strings[1] = NULL; + priv->combo = gtk_drop_down_new (); + gtk_drop_down_set_from_strings (GTK_DROP_DOWN (priv->combo), strings); + gtk_drop_down_set_selected (GTK_DROP_DOWN (priv->combo), 0); gtk_widget_set_sensitive (GTK_WIDGET (widget), FALSE); gtk_widget_show (priv->combo); gtk_box_append (GTK_BOX (widget), priv->combo); @@ -770,20 +961,17 @@ construct_widgets (GtkPrinterOptionWidget *widget) if (source->type == GTK_PRINTER_OPTION_TYPE_PICKONE) { priv->combo = combo_box_new (); - } + } else { priv->combo = combo_box_entry_new (); if (source->type == GTK_PRINTER_OPTION_TYPE_PICKONE_PASSWORD || - source->type == GTK_PRINTER_OPTION_TYPE_PICKONE_PASSCODE) - { - GtkEntry *entry; - - entry = GTK_ENTRY (gtk_combo_box_get_child (GTK_COMBO_BOX (priv->combo))); - - gtk_entry_set_visibility (entry, FALSE); - } + source->type == GTK_PRINTER_OPTION_TYPE_PICKONE_PASSCODE) + { + GtkWidget *entry = gtk_widget_get_first_child (priv->combo); + gtk_entry_set_visibility (GTK_ENTRY (entry), FALSE); + } } for (i = 0; i < source->num_choices; i++) @@ -792,7 +980,10 @@ construct_widgets (GtkPrinterOptionWidget *widget) source->choices[i]); gtk_widget_show (priv->combo); gtk_box_append (GTK_BOX (widget), priv->combo); - g_signal_connect (priv->combo, "changed", G_CALLBACK (combo_changed_cb), widget); + if (GTK_IS_DROP_DOWN (priv->combo)) + g_signal_connect (priv->combo, "notify::selected", G_CALLBACK (combo_changed_cb),widget); + else + g_signal_connect (gtk_widget_get_last_child (priv->combo), "notify::selected",G_CALLBACK (combo_changed_cb), widget); text = g_strdup_printf ("%s:", source->display_text); priv->label = gtk_label_new_with_mnemonic (text); @@ -951,9 +1142,7 @@ update_widgets (GtkPrinterOptionWidget *widget) case GTK_PRINTER_OPTION_TYPE_PICKONE_INT: case GTK_PRINTER_OPTION_TYPE_PICKONE_STRING: { - GtkEntry *entry; - - entry = GTK_ENTRY (gtk_combo_box_get_child (GTK_COMBO_BOX (priv->combo))); + GtkWidget *entry = gtk_widget_get_first_child (priv->combo); if (gtk_printer_option_has_choice (source, source->value)) combo_box_set (priv->combo, source->value); else -- 2.30.2